# This file is part of The Vu Toolkit.
#
# The Vu Toolkit is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# The Vu Toolkit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with The Vu Toolkit; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
#
# Copyright © Zak Fenton 2008
#

module Vu
	# Base class of the gadget heirachy
	class Gadget
		@parent = nil
	
		# Width and height of the gadget
		attr_reader :width, :height
		@width = 0
		@height = 0
		
		# An arbitrary name for the gadget. Can be used by the parent or the
		# application to denote special gadgets - "window_close", "default_button"
		attr_accessor :id
		@id = ""
		
		# Resizes the gadget (should only be called by parent's perform_layout)
		def resize! (w, h)
			w = w.round
			h = h.round
			if @width != w or @height != h
				@width = w
				@height = h
				resize_has_occured
			end
		end
		
		# Called when the gadget has been resized by a parent
		def resize_has_occured
		end
		
		# Width of a centimeter
		def cm_w
			if @parent
				@parent.cm_w
			else
				10
			end
		end
		
		# Height of a centimeter
		def cm_h
			if @parent
				@parent.cm_h
			else
				10
			end
		end
		
		# Minimum width
		def min_width
			20
		end
		
		# Minimum height
		def min_height
			20
		end
		
		# Attach this gadget to a parent. Only for internal use. (See detach_..)
		def attach_to_parent! (p)
			@parent = p
		end
		
		# Detaches this gadget from a parent (does NOT remove it from any of the
		# parent's data structures). Only for internal use.
		def detach_from_parent!
			@parent = nil
		end
		
		# The array of children
		def children
			[]
		end
		
		# The point of the X and Y origin of the window, in the parent's units
		@x_origin = 0
		@y_origin = 0
		attr_accessor :x_origin, :y_origin
		
		# Request that a section of the gadget be redrawn
		def request_render(x,y,w,h)
			if @parent
				@parent.request_render(x+@x_origin, y+@y_origin, w, h)
			end
		end
		
		# Request that the whole gadget be redrawn
		def request_render_all
			request_render(0,0,@width,@height)
		end
		
		# Renders only the child gadgets
		def render_children (cairo)
			for c in children
				cairo.translate(c.x_origin, c.y_origin)
				c.render(cairo)
				cairo.translate(-c.x_origin, -c.y_origin)
			end
		end
		
		# Paint the gadget on given Cairo context
		def render (cairo)
			render_children(cairo)
		end
		
		# The top level window the gadget is in
		def window
			if @parent
				@parent.window
			else
				false
			end
		end
		
		# Returns whomever - within the constraints of this gadget - owns mouse
		# events at the given position. Returns false, or [gadget, x, y] - where
		# gadget may be self, and x and y are in it's co-ordinate space.
		def contains? (x,y)
			if x >= 0 and y >= 0 and x <= width and y <= width
				# So we know it's inside our bounds (a subclass can add other 
				# constraints in an override, then call us). Now we see if it's
				# in a child's, or if not, return ourself
				result = [self, x, y]
				children.each do |c|
					c_c = c.contains?(x-c.x_origin,y-c.y_origin)
					result = c_c if c_c
				end
				return result
			else
				return false
			end
		end
		
		# Gives this gadget a mouse movement event
		def mouse_move (x,y)
		end
		
		# Gives this gadget a mouse enter event
		def mouse_enter
		end
		
		# Gives this gadget a mouse exit event
		def mouse_exit
		end
		
		# Gives this gadget a mouse button press/down event
		def mouse_press (b,x,y)
		end
		
		# Gives the gadget a mouse button release/up event
		def mouse_release (b,x,y)
		end
		
		# Gives this gadget a mouse click event
		def mouse_click (b,x,y)
		end
	end
end
